import * as THREE from 'three'
import { TransformControls } from 'three/addons/controls/TransformControls.js'
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
import { Line2 } from 'three/addons/lines/Line2.js';
import { LineGeometry } from 'three/addons/lines/LineGeometry.js';
import { KongZhi } from './KongZhi.js'
import { sheZhi } from '../cunChu/bianLiang.js'
import { huanJing } from '../huanJing/HuanJing.js'
import { GangTi } from '../changJing/wuTi/GangTi.js'
import { FaGuangTi } from '../changJing/wuTi/FaGuangTi.js'
import { Che } from '../changJing/wuTi/Che.js'
import { YueShu } from '../changJing/yueShu/YueShu.js'
import { JiaoLian } from '../changJing/yueShu/JiaoLian.js'
import { HuaKuai } from '../changJing/yueShu/HuaKuai.js'
import { gengXinJiHe } from '../gengXin/gengXin.js'
import { jieMian } from '../jieMian/zuJian/JieMian.js'
import { yeMianZhuanXiangJiZuoBiao } from '../gongJu/gongJu.js'
import { wuLiWorker } from '../wuLi/WuLiWorker.js'
import { ziYouShiJiao } from './ZiYouShiJiao.js'

// 编辑模式

let moRenKuaiJieJian = {
	xuanZhongMuBiao: {
		miaoShu: '选中目标',
		xiangQing: '选中目标',
		kuaiJieJian: 'Digit1'
	},
	quXiaoMuBiao: {
		miaoShu: '取消目标',
		xiangQing: '取消目标',
		kuaiJieJian: 'Digit2'
	},
	tianJiaGuDing: {
		miaoShu: '添加固定',
		xiangQing: '给选中的两个物体添加固定约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit3'
	},
	tianJiaJiaoLian: {
		miaoShu: '添加铰链',
		xiangQing: '给选中的两个物体添加铰链约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit4'
	},
	tianJiaHuaKuai: {
		miaoShu: '添加滑块',
		xiangQing: '给选中的两个物体添加滑块约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit5'
	},
	jiaYueShuFanWei: {
		miaoShu: '加约束范围/shift减范围',
		xiangQing: '给选中的约束增加约束范围，同时按住shift减少范围',
		kuaiJieJian: 'Digit6'
	},
	suoFangBianHuan: {
		miaoShu: '缩放变换',
		xiangQing: '变换控制器缩放模式（物体、约束不能缩放）',
		kuaiJieJian: 'Digit7'
	},
	xuanZhuanBianHuan: {
		miaoShu: '旋转变换',
		xiangQing: '变换控制器旋转模式',
		kuaiJieJian: 'Digit8'
	},
	pingYiBianHuan: {
		miaoShu: '平移变换',
		xiangQing: '变换控制器平移模式',
		kuaiJieJian: 'Digit9'
	},
	tianJiaZiWuTiHuoXingZhuang: {
		miaoShu: '添加子物体或形状',
		xiangQing: '给选中的物体在参考点位置添加子物体；或编辑物体是在参考点位置添加形状（物体的质点为原点）',
		kuaiJieJian: 'KeyC'
	},
	bianJiWuTi: {
		miaoShu: '编辑物体模式切换',
		xiangQing: '选中物体编辑形状，再次按下返回物体模式',
		kuaiJieJian: 'KeyV'
	},
	shanChuMuBiao: {
		miaoShu: '删除目标',
		xiangQing: '删除选中的物体、约束或形状',
		kuaiJieJian: 'KeyX'
	}
}

Object.defineProperty(moRenKuaiJieJian, 'miaoShu', {
	value: '编辑模式',
	enumerable: false
})

let bianJiMoShi = null

class BianJiMoShi extends KongZhi {
	kuaiJieJianBianHao = 'BianJiMoShi'
	kuaiJieJian = null
	moShi = 0 // 0 物体模式，1 编辑模式
	qiYongXuanZhong = true // 是否启用指针选中目标
	canKaoDian = null // 添加物体、形状的参考点
	dianWeiZhi = null // 指针位置
	muBiao = null // 选中的边框目标
	bianHuanMuBiao = null // 变换的目标
	bianJiMuBiao = null // 编辑的物体目标
	yueShuWuTi = new Set() // 要约束的两个物体
	kongZhiQi = null // 变换控制器
	
	constructor() {
		super()
		
		if (sheZhi.kuaiJieJian[this.kuaiJieJianBianHao]) this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] // 从存储中加载快捷键
		else this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] = moRenKuaiJieJian

		bianJiMoShi = this
		
		this.shengChengKogZhiQi()
		// 参考点
		let svg = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`
			<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
				<circle cx="50" cy="50" r="50" fill="#fff"/>
			</svg>
		`)}`;
		let wenLi = new THREE.TextureLoader().load(svg)
		this.canKaoDian = new THREE.Sprite(new THREE.SpriteMaterial({ map: wenLi, depthTest: false, sizeAttenuation: false }))
		this.canKaoDian.scale.set(0.015, 0.015, 0.015)
		this.canKaoDian.layers.enable(huanJing.houQiChuLi.BLOOM_SCENE)
	}
	
	chuLi(shiJian) {
		if (shiJian.type == 'pointermove') this.zhiZhenJingGuo(shiJian)
		if (shiJian.type == 'keydown') this.keydown(shiJian)
	}
	
	keydown(shiJian) {
		let kjj = this.kuaiJieJian
		let shiftKey = shiJian.shiftKey

		switch (shiJian.code) {
			case kjj.xuanZhongMuBiao.kuaiJieJian:
				this.xuanZhongMuBiao(this.muBiao)
				break;
			case kjj.quXiaoMuBiao.kuaiJieJian:
				this.quXiaoMuBiao(this.muBiao)
				break;
			case kjj.tianJiaGuDing.kuaiJieJian:
				this.tianJiaGuDing()
				break;
			case kjj.tianJiaJiaoLian.kuaiJieJian:
				this.tianJiaJiaoLian()
				break;
			case kjj.tianJiaHuaKuai.kuaiJieJian:
				this.tianJiaHuaKuai()
				break;
			case kjj.jiaYueShuFanWei.kuaiJieJian:
				this.jiaYueShuFanWei(shiftKey)
				break;
			case kjj.suoFangBianHuan.kuaiJieJian:
				this.qieHuanBianHuanMoShi('scale')
				break;
			case kjj.xuanZhuanBianHuan.kuaiJieJian:
				this.qieHuanBianHuanMoShi('rotate')
				break;
			case kjj.pingYiBianHuan.kuaiJieJian:
				this.qieHuanBianHuanMoShi('translate')
				break;
			case kjj.tianJiaZiWuTiHuoXingZhuang.kuaiJieJian:
				this.tianJiaZiWuTiHuoXingZhuang()
				break;
			case kjj.bianJiWuTi.kuaiJieJian:
				this.bianJiWuTi()
				break;
			case kjj.shanChuMuBiao.kuaiJieJian:
				this.shanChuMuBiao()
				break;
		}
	}
	// 生成控制器
	shengChengKogZhiQi() {
		this.kongZhiQi = new TransformControls( huanJing.camera, huanJing.renderer.domElement );
		this.kongZhiQi.space = 'local'
		// 解决跟辉光效果darkMaterial冲突问题
		let updateMatrixWorld = new THREE.Object3D().updateMatrixWorld
		this.kongZhiQi._gengXin = this.kongZhiQi.updateMatrixWorld
		this.kongZhiQi.updateMatrixWorld = updateMatrixWorld
		this.kongZhiQi._gizmo.gengXin = this.kongZhiQi._gizmo.updateMatrixWorld
		this.kongZhiQi._gizmo.updateMatrixWorld = updateMatrixWorld
		this.kongZhiQi._plane.gengXin = this.kongZhiQi._plane.updateMatrixWorld
		this.kongZhiQi._plane.updateMatrixWorld = updateMatrixWorld
		this.kongZhiQi._plane.visible = false

		this.kongZhiQi.gengXin = () => {
			if (!this.kongZhiQi.object?.parent) this.kongZhiQi.detach()
			this.kongZhiQi._gengXin()
			this.kongZhiQi._gizmo.gengXin()
			this.kongZhiQi._plane.gengXin()
		}

		this.kongZhiQi.addEventListener( 'objectChange', this.gengXinBianHuan.bind(this));
		this.kongZhiQi.addEventListener( 'dragging-changed', ( event ) => {
			this.qiYongXuanZhong = ziYouShiJiao.qiYong = ! event.value;

			this.bianHuanGuoLv()
		} );
	}
	// 加载控制器
	jiaZaiKongZhiQi(chanShu) {
		if (chanShu) huanJing.scene.add(this.kongZhiQi)
		else {
			this.kongZhiQi.detach()
			this.kongZhiQi.removeFromParent()
		}

		this.kongZhiQi.enable = chanShu
	}
	// 切换控制器变换模式
	qieHuanBianHuanMoShi(chanShu) {
		if (!this.kongZhiQi.visible) return

		this.kongZhiQi.setMode(chanShu)
	}
	// 指针经过
	zhiZhenJingGuo(shiJian) {
		// 射线检测有性能问题（特别是行星模型多顶点）
		if (document.pointerLockElement != null) return
		if (!this.qiYongXuanZhong) return

		let zuoBiao = new THREE.Vector2(...yeMianZhuanXiangJiZuoBiao(shiJian.offsetX, shiJian.offsetY))
		let raycaster = new THREE.Raycaster()
		raycaster.setFromCamera( zuoBiao, huanJing.camera )
		
		let jianCeMoXing = []

		if (this.moShi === 0) {
			huanJing.scene.traverseVisible(a => {
				let muBiao = a.userData.huoQuYueShu?.() ?? a.userData.huoQuWuTi?.()
				if (muBiao) {
					if (muBiao.shiHengXing) return
	
					if (a.isMesh && !a.isSprite && !a.isInstancedMesh && !a.isLine2) jianCeMoXing.push(a)
				}
			})
		} else if (this.moShi === 1) {
			this.bianJiMuBiao?.moXing.traverseVisible(a => {
				let muBiao = a.userData.huoQuWuTi?.()
				if (muBiao && muBiao == this.bianJiMuBiao && a.userData.pengZhuangTiUUID) {
					if (muBiao.shiXingXing) return
	
					if (a.isMesh && !a.isSprite && !a.isInstancedMesh && !a.isLine2) jianCeMoXing.push(a)
				}
			})
		}

		let xiangJiao = raycaster.intersectObjects(jianCeMoXing, false)

		if ( xiangJiao.length > 0 ) {
			if (this.moShi === 0) {
				let yueShu = xiangJiao.find(a => a.object.userData.huoQuYueShu)
				let xj = yueShu || xiangJiao[0]
				let { object, point } = xj

				this.dianWeiZhi = point.clone()
				this.canKaoDian.position.copy(point)
				huanJing.scene.add(this.canKaoDian)
				
				this.muBiao = object.userData.huoQuYueShu?.() ?? object.userData.huoQuWuTi?.()

				huanJing.houQiChuLi.bianKuang.selectedObjects = [this.muBiao.moXing]
			} else if (this.moShi === 1) {
				let xj = xiangJiao[0]
				let { object, point } = xj

				this.dianWeiZhi = point.clone()
				this.canKaoDian.position.copy(point)
				huanJing.scene.add(this.canKaoDian)

				this.muBiao = object

				huanJing.houQiChuLi.bianKuang.selectedObjects = [object]
			}
		} else {
			huanJing.houQiChuLi.bianKuang.selectedObjects = []
			this.canKaoDian.removeFromParent()
			this.dianWeiZhi = null
			this.muBiao = null
		}
	}
	/**
	 * 目标线框显示切换
	 * @param {GangTi|YueShu|Object} muBiao
	 * @param {Boolean} xianShi 
	 * @returns 
	 */
	xianKuang(muBiao, xianShi) {
		function tianJiaXianKuang(wangGe) {
			let xk = shengChengXianKuang(wangGe.geometry)
			xk.userData.shiXianKuang = true
			wangGe.add(xk)
		}

		let shanChu = [] // 待删除线框

		if (muBiao.moXing.children.includes(a => a.userData.shiXianKuang)) return

		if (muBiao.shiGangTi) {
			muBiao.moXing.traverseVisible(a => {
				if (a.isMesh && a.userData.huoQuWuTi && a.userData.huoQuWuTi() == muBiao && xianShi) tianJiaXianKuang(a)
				if (!xianShi && a.userData.shiXianKuang) shanChu.push(a)
			})
		} else if (muBiao.shiYueShu) {
			muBiao.moXing.traverseVisible(a => {
				if (a.isMesh && a.userData.huoQuYueShu && a.userData.huoQuYueShu() == muBiao && xianShi) tianJiaXianKuang(a)
				if (!xianShi && a.userData.shiXianKuang) shanChu.push(a)
			})
		} else {
			muBiao.moXing.traverse(a => {
				if (a.isMesh && !a.userData.shiXianKuang && xianShi) tianJiaXianKuang(a)
				else if (!xianShi && a.userData.shiXianKuang) shanChu.push(a)
			})
		}

		for (let i = 0, l = shanChu.length; i < l; i++) {
			shanChu[i].removeFromParent()
		}
	}
	// 选中约束物体或要变换的约束、形状
	xuanZhongMuBiao(muBiao) {

		if (muBiao) {
			if (this.moShi === 0) {
				if (muBiao.shiGangTi) {
					this.yueShuWuTi.add(muBiao)
					if (this.yueShuWuTi.size == 3) this.quXiaoMuBiao([...this.yueShuWuTi][0])
				}

				if (this.bianHuanMuBiao?.shiYueShu) this.quXiaoMuBiao(this.bianHuanMuBiao)

				this.bianHuanMuBiao = muBiao
				this.kongZhiQi.attach(muBiao.moXing)
				this.xianKuang(muBiao, true)
			}

			if (this.moShi === 1) {
				if (this.bianHuanMuBiao) this.quXiaoMuBiao(this.bianHuanMuBiao)

				this.bianHuanMuBiao = muBiao
				this.kongZhiQi.attach(muBiao)
				this.xianKuang({ moXing: muBiao }, true)
			}
		}
	}
	// 取消选中约束物体或要变换的约束、形状
	quXiaoMuBiao(muBiao) {
		if (muBiao) {
			if (this.moShi === 0) {
				if (muBiao.shiGangTi && this.yueShuWuTi.has(muBiao)) {
					this.yueShuWuTi.delete(muBiao)
					this.xianKuang(muBiao, false)
				}

				if (muBiao == this.bianHuanMuBiao) {
					this.bianHuanMuBiao = null
					this.kongZhiQi.detach()
					this.xianKuang(muBiao, false)
				}
			}

			if (this.moShi === 1) {
				this.bianHuanMuBiao = null
				this.kongZhiQi.detach()
				this.xianKuang({ moXing: muBiao }, false)
			}
		}
	}
	// 清空选中的约束物体或要变换的约束、形状
	qingKongMuBiao() {
		if (this.moShi === 0) {
			this.yueShuWuTi.forEach(a => this.quXiaoMuBiao(a))
			this.yueShuWuTi.clear()

			if (this.bianHuanMuBiao) {
				this.kongZhiQi.detach()
				this.xianKuang(this.bianHuanMuBiao, false)
				this.bianHuanMuBiao = null
			}
		}

		if (this.moShi === 1) {
			this.bianJiMuBiao = null

			if (this.bianHuanMuBiao) {
				this.kongZhiQi.detach()
				this.xianKuang({ moXing: this.bianHuanMuBiao }, false)
				this.bianHuanMuBiao = null
			}
		}
	}
	// 打开编辑面板
	daKaiBianJiMianBan(wuTiCanShu) {
		let mianBan = jieMian.bianJiMianBan

		if (wuTiCanShu) {
			mianBan.chongZhi()
			mianBan.daKai()

			let qieHuanShuZu = []

			if (this.moShi === 0) {
				mianBan.biaoTi.textContent = '添加物体'

				let wuTiXuanXiang = mianBan.tianJiaXiang({ leiXing: '选项', mingZi: '物体', zhi: wuTiCanShu.wuTi, xuanXiang: ['基础物体', '发光体', '车'] })
				wuTiXuanXiang.gengXin = zhi => {
					wuTiCanShu.wuTi = zhi
					shuaXin()
				}
			} else if (this.moShi === 1) {
				mianBan.biaoTi.textContent = '添加形状'
			}

			let xingZhuangXuanXiang = mianBan.tianJiaXiang({ leiXing: '选项', mingZi: '几何形状', zhi: wuTiCanShu.xingZhuang, xuanXiang: ['方体', '球体', '胶囊', '圆锥', '圆柱'] })
			xingZhuangXuanXiang.gengXin = zhi => {
				wuTiCanShu.xingZhuang = zhi
				shuaXin()
			}

			let kuan = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '宽', zhi: wuTiCanShu.kuan, zuiDa: 100, zuiXiao: 0 })
			kuan.gengXin = zhi => wuTiCanShu.kuan = zhi
			let gao = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '高', zhi: wuTiCanShu.gao, zuiDa: 100, zuiXiao: 0 })
			gao.gengXin = zhi => wuTiCanShu.gao = zhi
			let shen = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '深', zhi: wuTiCanShu.shen, zuiDa: 100, zuiXiao: 0 })
			shen.gengXin = zhi => wuTiCanShu.shen = zhi
			let banJing = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '半径', zhi: wuTiCanShu.banJing, zuiDa: 100, zuiXiao: 0 })
			banJing.gengXin = zhi => wuTiCanShu.banJing = zhi
			let chang = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '长', zhi: wuTiCanShu.chang, zuiDa: 10, zuiXiao: 0 })
			chang.gengXin = zhi => wuTiCanShu.chang = zhi
			let diPanKuan = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '底盘宽', zhi: wuTiCanShu.diPanKuan, zuiDa: 2.1, zuiXiao: 2 })
			diPanKuan.gengXin = zhi => wuTiCanShu.diPanKuan = zhi
			let diPanGao = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '底盘高', zhi: wuTiCanShu.diPanGao, zuiDa: 0.23, zuiXiao: 0.22 })
			diPanGao.gengXin = zhi => wuTiCanShu.diPanKuan = zhi
			let diPanShen = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '底盘深', zhi: wuTiCanShu.diPanShen, zuiDa: 5, zuiXiao: 4.5 })
			diPanShen.gengXin = zhi => wuTiCanShu.diPanKuan = zhi
			let zhiLiang = mianBan.tianJiaXiang({ leiXing: '数字', mingZi: '质量', zhi: wuTiCanShu.zhiLiang, zuiDa: 10000, zuiXiao: 1 })
			zhiLiang.gengXin = zhi => wuTiCanShu.zhiLiang = zhi
			let yanSe = mianBan.tianJiaXiang({ leiXing: '颜色', mingZi: '颜色', zhi: wuTiCanShu.yanSe })
			yanSe.gengXin = zhi => wuTiCanShu.yanSe = zhi

			qieHuanShuZu.push(kuan, gao, shen, banJing, chang, diPanKuan, diPanGao, diPanShen, zhiLiang, yanSe)

			let shuaXin = () => {
				qieHuanShuZu.forEach(a => a.style.display = 'none')

				let wuTi = wuTiCanShu.wuTi
				let xingZhuang = wuTiCanShu.xingZhuang

				if (xingZhuang == '方体') {
					kuan.style.display = 'flex'
					gao.style.display = 'flex'
					shen.style.display = 'flex'
				}
				if (xingZhuang == '球体') banJing.style.display = 'flex'
				if (xingZhuang == '胶囊') {
					banJing.style.display = 'flex'
					chang.style.display = 'flex'
				}
				if (xingZhuang == '圆锥' || xingZhuang == '圆柱') {
					banJing.style.display = 'flex'
					gao.style.display = 'flex'
				}

				if (wuTi == '车') {
					kuan.setAttribute('zhi', wuTiCanShu.diPanKuan)
					gao.setAttribute('zhi', wuTiCanShu.diPanGao)
					shen.setAttribute('zhi', wuTiCanShu.diPanShen)

					diPanKuan.style.display = 'flex'
					diPanGao.style.display = 'flex'
					diPanShen.style.display = 'flex'
				}

				yanSe.style.display = 'flex'
				if (this.moShi === 0) zhiLiang.style.display = 'flex'
			}

			shuaXin()

		} else {
			mianBan.guanBi()
			huanJing.renderer.domElement.focus()
		}
		
		this.qiYongXuanZhong = !Boolean(wuTiCanShu)
	}
	// 添加子物体或形状
	tianJiaZiWuTiHuoXingZhuang() {
		// 没有参考点 不添加
		if (!this.dianWeiZhi) return

		let bianHuanMuBiao = this.bianHuanMuBiao
		let bianJiMuBiao = this.bianJiMuBiao

		let wuTiCanShu = {
			wuTi: '基础物体',
			xingZhuang: '方体',
			kuan: 1,
			gao: 1,
			shen: 1,
			banJing: 0.5,
			chang: 1,
			zhiLiang: 10,
			yanSe: '#aaccff',
			diPanKuan: 2,
			diPanGao: 0.22,
			diPanShen: 4.5
		}

		if (this.moShi === 0 && bianHuanMuBiao?.shiGangTi) {
			// 打开编辑面板
			this.daKaiBianJiMianBan(wuTiCanShu)
			// 编辑函数
			let bianJi = () => {
				// 可编辑物体模型需由小到看不到的网格开始，碰撞模型需要由组合形状的组对象开始
				let wuTiMoXing = new THREE.Mesh(new THREE.BoxGeometry(0.001, 0.001, 0.001))
				let wuTipengZhuangTi = new THREE.Group()
				wuTipengZhuangTi.userData.xingZhuang = '组合'

				let { moXing, pengZhuangTi } = this.shengChengXingZhuang(wuTiCanShu)

				wuTiMoXing.add(moXing)
				wuTipengZhuangTi.add(pengZhuangTi)

				let weiZhi = this.dianWeiZhi.clone()
				this.muBiao.moXing.worldToLocal(weiZhi)
				wuTiMoXing.position.copy(weiZhi)

				let wuTi = null

				if (wuTiCanShu.wuTi === '发光体') {
					wuTi = new FaGuangTi(wuTiMoXing, wuTipengZhuangTi, wuTiCanShu.zhiLiang, wuTiCanShu.yanSe)
				} else if (wuTiCanShu.wuTi === '车') {
					let chiCun = new THREE.Vector3(wuTiCanShu.diPanKuan, wuTiCanShu.diPanGao, wuTiCanShu.diPanShen)
					wuTi = new Che(wuTiMoXing, wuTipengZhuangTi, chiCun)
				} else {
					wuTi = new GangTi(wuTiMoXing, wuTipengZhuangTi, wuTiCanShu.zhiLiang)
				}

				wuTi.fu = this.muBiao
				this.muBiao.zi.add(wuTi)

				wuTi.jiaZai()

				this.xuanZhongMuBiao(wuTi)

				this.daKaiBianJiMianBan(false)
			}

			jieMian.bianJiMianBan.queDing = bianJi
			jieMian.bianJiMianBan.quXiao = () => this.daKaiBianJiMianBan(false)
		} else if (this.moShi === 1) {
			this.daKaiBianJiMianBan(wuTiCanShu)

			let bianJi = () => {
				let { moXing, pengZhuangTi } = this.shengChengXingZhuang(wuTiCanShu)

				let weiZhi = this.dianWeiZhi.clone()
				bianJiMuBiao.moXing.worldToLocal(weiZhi)
				moXing.position.copy(weiZhi)

				bianJiMuBiao.bianJiXingZhuang({ bianJiLeiXing: 0, moXing, pengZhuangTi })

				this.xuanZhongMuBiao(moXing)

				this.daKaiBianJiMianBan(false)
			}

			jieMian.bianJiMianBan.queDing = bianJi
			jieMian.bianJiMianBan.quXiao = () => this.daKaiBianJiMianBan(false)
		}
	}
	// 生成形状体
	shengChengXingZhuang(xingZhuangCanShu) {
		let jiHeTi = null

		if (xingZhuangCanShu.xingZhuang == '方体') {
			let { kuan, gao, shen } = xingZhuangCanShu
			jiHeTi = new THREE.BoxGeometry(kuan, gao, shen)
		}
		if (xingZhuangCanShu.xingZhuang == '球体') {
			let { banJing } = xingZhuangCanShu
			jiHeTi = new THREE.SphereGeometry(banJing, 16, 8)
		}
		if (xingZhuangCanShu.xingZhuang == '胶囊') {
			let { banJing, chang } = xingZhuangCanShu
			jiHeTi = new THREE.CapsuleGeometry(banJing, chang, 2, 8)
		}
		if (xingZhuangCanShu.xingZhuang == '圆锥') {
			let { banJing, gao } = xingZhuangCanShu
			jiHeTi = new THREE.ConeGeometry(banJing, gao, 16)
		}
		if (xingZhuangCanShu.xingZhuang == '圆柱') {
			let { banJing, gao } = xingZhuangCanShu
			jiHeTi = new THREE.CylinderGeometry(banJing, banJing, gao, 16)
		}

		let pengZhuangTi = new THREE.Mesh(jiHeTi, new THREE.MeshBasicMaterial())
		pengZhuangTi.userData.xingZhuang = xingZhuangCanShu.xingZhuang

		let caiZhi = new THREE.MeshStandardMaterial({ color: xingZhuangCanShu.yanSe})
		let moXing = new THREE.Mesh(jiHeTi, caiZhi)
		// 可编辑模型需跟碰撞模型关联
		moXing.userData.pengZhuangTiUUID = pengZhuangTi.uuid
		moXing.castShadow = true
		moXing.receiveShadow = true

		return { moXing, pengZhuangTi }
	}
	// 编辑物体形状
	bianJiWuTi() {
		let bianHuanMuBiao = this.bianHuanMuBiao

		if (this.moShi === 0) {
			if (bianHuanMuBiao && bianHuanMuBiao.shiGangTi) {
				if (bianHuanMuBiao.pengZhuangTi.userData.xingZhuang !== '组合') return

				this.bianJiMuBiao = bianHuanMuBiao
				this.qingKongMuBiao()
				huanJing.houQiChuLi.bianKuang.selectedObjects = []
				this.dianWeiZhi = null
				this.muBiao = null
				this.moShi = 1
				// 切换技能条
				this.guanBiJieMian()
				this.daKaiJieMian()
			}
		} else if (this.moShi === 1) {
			this.qingKongMuBiao()
			this.moShi = 0

			this.guanBiJieMian()
			this.daKaiJieMian()
		}
		
	}
	// 变换过滤
	bianHuanGuoLv() {
		let bianHuanMuBiao = this.bianHuanMuBiao
		let bianHuanMoShi = this.kongZhiQi.getMode()

		if (bianHuanMuBiao.shiXingXing) this.kongZhiQi.dragging = false
		if ((bianHuanMuBiao.shiGangTi || bianHuanMuBiao.shiYueShu) && bianHuanMoShi == 'scale') this.kongZhiQi.dragging = false
	}
	// 更新控制器变换结果
	gengXinBianHuan() {
		let bianHuanMoShi = this.kongZhiQi.getMode()
		let bianHuanMuBiao = this.bianHuanMuBiao

		if (this.moShi === 0) {
			if (bianHuanMuBiao) {
				if (bianHuanMuBiao.shiYueShu) return this.gengXinYueShu()

				if (bianHuanMuBiao.shiGangTi) {
					function chuLi(muBiao) {
						let sheZhiCanShu = {}
						/*
							模型世界物体的缩放是相对于父模型
							物理世界物体的缩放是相对于世界
							所以物体不支持缩放
						*/
						// if (bianHuanMoShi == 'scale') {
						// 	let suoFang = new THREE.Vector3()
						// 	suoFang.copy(muBiao.moXing.scale)
						// 	sheZhiCanShu.suoFang = suoFang
						// }
						if (bianHuanMoShi == 'rotate') {
							let xuanZhuan = new THREE.Quaternion()
							muBiao.moXing.getWorldQuaternion(xuanZhuan).normalize()
							sheZhiCanShu.xuanZhuan = xuanZhuan
						}
						if (bianHuanMoShi == 'translate') {
							let weiZhi = new THREE.Vector3()
							muBiao.moXing.getWorldPosition(weiZhi)
							sheZhiCanShu.weiZhi = weiZhi
						}
				
						muBiao.sheZhiPengZhuangTi(sheZhiCanShu)

						muBiao.zi.forEach(a => chuLi(a))
					}
					
					chuLi(bianHuanMuBiao)
				}
			}
		} else if (this.moShi === 1) {
			if (bianHuanMuBiao) {
				this.bianJiMuBiao.bianJiXingZhuang({ bianJiLeiXing: 1, moXing: bianHuanMuBiao })
			}
		}
	}
	// 添加固定
	tianJiaGuDing() {
		if (this.moShi !== 0) return
		if (!this.dianWeiZhi) return

		let yueShuWuTi = this.yueShuWuTi
		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.dianWeiZhi
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
			
			let yueShu = new YueShu('固定', { wuTiA, wuTiB, weiZhiA, weiZhiB })
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 添加铰链
	tianJiaJiaoLian() {
		if (this.moShi !== 0) return
		if (!this.dianWeiZhi) return

		let yueShuWuTi = this.yueShuWuTi
		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.dianWeiZhi
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
	
			let yueShu = new JiaoLian(wuTiA, wuTiB, weiZhiA, weiZhiB)
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 添加滑块
	tianJiaHuaKuai() {
		if (this.moShi !== 0) return
		if (!this.dianWeiZhi) return

		let yueShuWuTi = this.yueShuWuTi
		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.dianWeiZhi
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
	
			let yueShu = new HuaKuai(wuTiA, wuTiB, weiZhiA, weiZhiB)
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 更新约束
	gengXinYueShu() {
		if (this.moShi !== 0) return

		if (this.bianHuanMuBiao?.shiYueShu) {
			this.bianHuanMuBiao.gengXinYueShuCanShu()
			this.bianHuanMuBiao.xieZai()
			this.bianHuanMuBiao.jiaZai()
		}
	}
	// 约束加范围
	jiaYueShuFanWei(shiftKey = false) {
		if (this.moShi !== 0) return

		let bianHuanMuBiao = this.bianHuanMuBiao

		if (bianHuanMuBiao && bianHuanMuBiao.yueShuFanWei) {
			let zuiXiao = 0, zuiDa = 0
			let liang = 0 // 每次增减量
			let yueShuFanWei = bianHuanMuBiao.yueShuFanWei
			
			if (bianHuanMuBiao.yueShuLeiXing == '铰链') {
				zuiXiao = 0
				zuiDa = Math.PI * 1.999
				liang = Math.PI / 180
			}
			if (bianHuanMuBiao.yueShuLeiXing == '滑块') {
				zuiXiao = 0
				zuiDa = 10
				liang = 0.1
			}
			
			if (shiftKey) yueShuFanWei.zuiDa = Math.max(zuiXiao, yueShuFanWei.zuiDa - liang)
			else yueShuFanWei.zuiDa = Math.min(zuiDa, yueShuFanWei.zuiDa + liang)
			
			bianHuanMuBiao.gengXinJiHeTi(bianHuanMuBiao.moXing)
		}
	}
	// 删除目标
	shanChuMuBiao() {
		let bianHuanMuBiao = this.bianHuanMuBiao

		if (bianHuanMuBiao) {
			if (bianHuanMuBiao.shiXingXing) return

			if (this.moShi === 0) {
				this.xianKuang(bianHuanMuBiao, false)
				this.kongZhiQi.detach()

				if (bianHuanMuBiao.shiGangTi) {
					if (this.yueShuWuTi.has(bianHuanMuBiao)) this.yueShuWuTi.delete(bianHuanMuBiao)
					bianHuanMuBiao.zi.forEach(a => a.xiaoHui())
				}
				bianHuanMuBiao.xiaoHui()
				this.bianHuanMuBiao = null
			}

			if (this.moShi === 1) {
				this.xianKuang({ moXing: bianHuanMuBiao }, false)
				this.kongZhiQi.detach()

				this.bianJiMuBiao.bianJiXingZhuang({ bianJiLeiXing: 2, moXing: bianHuanMuBiao })

				this.bianHuanMuBiao = null
			}
		}
	}
	// 显示约束模型
	xianShiYueShu(xianShi) {
		for (let i = 0, l = YueShu.quanBuYueShu.length; i < l; i++) {
			let yueShu = YueShu.quanBuYueShu[i]
			if (!yueShu.shiKongZhiTi) yueShu.moXing.visible = xianShi
		}
	}
	// 打开界面
	daKaiJieMian() {
		// 生成技能条
		let jiNengTiao = jieMian.jiNengTiao
		jiNengTiao.shadowRoot.innerHTML = ''
		
		for(let i in this.kuaiJieJian) {
			let jiNeng = this.kuaiJieJian[i]

			if (this.moShi === 0) {
				if (i == 'suoFangBianHuan') continue
			}

			if (this.moShi === 1) {
				if (i == 'tianJiaGuDing' || i == 'tianJiaJiaoLian' || i == 'tianJiaHuaKuai' || i == 'jiaYueShuFanWei') continue
			}
			
			jiNengTiao.shengChengJiNeng(jiNeng)
		}
	}
	// 关闭界面
	guanBiJieMian() {
		//  删除技能条
		let jiNengTiao = jieMian.jiNengTiao
		jiNengTiao.shadowRoot.innerHTML = ''
		// 关闭编辑面板
		this.daKaiBianJiMianBan(false)
	}
	
	gengXin() {
		this.kongZhiQi.gengXin()
	}
	
	jiaZai() {
		super.jiaZai()
		this.moShi = 0
		this.muBiao = null
		this.qiYongXuanZhong = true
		this.jiaZaiKongZhiQi(true)
		this.xianShiYueShu(true)
		this.daKaiJieMian()

		gengXinJiHe.set(this, this.gengXin.bind(this))
		wuLiWorker.tingZhiMoNi(true)
		huanJing.renderer.shadowMap.enabled = false
	}
	
	xieZai() {
		super.xieZai()
		this.qingKongMuBiao()
		this.xianShiYueShu(false)
		this.jiaZaiKongZhiQi(false)
		this.guanBiJieMian()
		this.canKaoDian.removeFromParent()

		gengXinJiHe.delete(this)
		wuLiWorker.tingZhiMoNi(false)
		huanJing.houQiChuLi.bianKuang.selectedObjects = []
		huanJing.renderer.shadowMap.enabled = true
	}
}

function shengChengXianKuang(geometry) {
	const matLine = new LineMaterial({ color: 0xffffff, linewidth: 0.03, transparent: true, opacity: 0.3, worldUnits: true, vertexColors: true } )
	let xianKuang = new Line2( new LineGeometry(), matLine );
	xianKuang.name = '边框'
	xianKuang.layers.enable(huanJing.houQiChuLi.BLOOM_SCENE)

	const edges = new THREE.EdgesGeometry(geometry);
	let dingDian = edges.attributes.position.array
	let divisions = Math.round(dingDian.length / 3)
	let colors = []
	const color = new THREE.Color();
	for ( let i = 0, l = divisions; i < l; i ++ ) {
		const t = i / l;
		color.setHSL( t, 1.0, 0.5, THREE.SRGBColorSpace );
		colors.push( color.r, color.g, color.b );
	}
	const lineGeometry = xianKuang.geometry
	lineGeometry.setPositions(dingDian)
	lineGeometry.setColors( colors );
	xianKuang.computeLineDistances();
	xianKuang.scale.set( 1, 1, 1 );
	xianKuang.userData.buCunDang = true
	
	edges.dispose()

	return xianKuang
}

export {
	BianJiMoShi,
	bianJiMoShi
};